﻿using STEditor.Classes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.ObjectModel;
using System.Windows.Media.Imaging;
using System.Linq;

namespace STEditor.Classes.Tests
{

    [TestClass]
    public class STGameAreaTest
    {

        private STGameArea _gameArea;

        [TestInitialize]
        public void Initialize()
        {
            _gameArea = new STGameArea();
        }

        [TestMethod]
        public void STGameArea_Should_Have_Tiles_Property()
        {
            Assert.IsInstanceOfType(_gameArea.Tiles, typeof(ObservableCollection<STTile>), "Tiles is not an ObservableCollections<STTile>");
        }

        [TestMethod]
        public void STGameArea_Should_Have_Width_And_Height()
        {

            int expectedWidth = 2;
            int expectedHeight = 3;

            _gameArea.Width = expectedWidth;
            _gameArea.Height = expectedHeight;

            Assert.AreEqual(expectedWidth, _gameArea.Width, "Width was not set correctly");
            Assert.AreEqual(expectedHeight, _gameArea.Height, "Height was not set correctly");

        }

        [TestMethod]
        public void Width_And_Height_Should_Determine_Size_Of_Tiles_Collection()
        {

            int expectedWidth = 2;
            int expectedHeight = 3;

            _gameArea.Width = expectedWidth;
            _gameArea.Height = expectedHeight;

            Assert.AreEqual(expectedWidth * expectedHeight, _gameArea.Tiles.Count, "Count of tiles array does not match expected number of tiles");

        }

        [TestMethod]
        public void Tiles_Collection_Should_Initially_Be_Filled_With_EmptyTile_Objects()
        {
            int expectedWidth = 2;
            int expectedHeight = 3;

            _gameArea.Width = expectedWidth;
            _gameArea.Height = expectedHeight;

            CollectionAssert.AllItemsAreInstancesOfType(_gameArea.Tiles, typeof(EmptyTile), "Not all tiles are instances of EmptyTile");

        }

        [TestMethod]
        public void STGameArea_Should_Know_Its_Owning_Game()
        {

            var game = new STGame();
            game.GameAreas.Add(_gameArea);

            Assert.AreSame(game, _gameArea.Game, "Game was not set correctly");

        }

        [TestMethod]
        public void STGameArea_Should_Have_TileWidth_And_TileHeight_Properties()
        {

            int expectedTileWidth = 10;
            int expectedTileHeight = 20;

            _gameArea.TileWidth = expectedTileWidth;
            _gameArea.TileHeight = expectedTileHeight;

            Assert.AreEqual(expectedTileWidth, _gameArea.TileWidth, "TileWidth was not set correctly");
            Assert.AreEqual(expectedTileHeight, _gameArea.TileHeight, "TileHeight was not set correctly");

        }

        [TestMethod]
        public void SetTile_Should_Replace_Tile_At_Existing_Position()
        {

            _gameArea.TileWidth = 20;
            _gameArea.TileHeight = 20;
            _gameArea.Width = 2;
            _gameArea.Height = 2;

            var currentTile = _gameArea
                .Tiles
                .Where(t => t.X == 0 && t.Y == 0)
                .Single();

            var newImage = new STFrame();
            _gameArea.SetTile(0, 0, newImage);

            var newTile = _gameArea
                .Tiles
                .Where(t => t.X == 0 && t.Y == 0)
                .Single();

            Assert.AreNotSame(currentTile, newTile, "New tile did not replace current tile");
            Assert.AreSame(newImage, newTile.Image, "New tile image is not the same as the current tile image");

        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void SetTile_Should_Fail_If_Replacing_A_Tile_That_Doesnt_Exist()
        {

            _gameArea.TileWidth = 20;
            _gameArea.TileHeight = 20;
            _gameArea.Width = 2;
            _gameArea.Height = 2;

            var newImage = new STFrame();
            _gameArea.SetTile(2, 2, newImage); 

        }

        [TestMethod]
        public void SetTile_Should_Allow_Setting_The_Tile_To_The_Selected_Tile()
        {

            var game = new STGame();
            game.TileTypes.SelectedTile = EmptyTile.EmptyImage;

            game.GameAreas.Add(_gameArea);

            _gameArea.TileWidth = 20;
            _gameArea.TileHeight = 20;
            _gameArea.Width = 2;
            _gameArea.Height = 2;

            _gameArea.SetTile(0, 0);
            
            var newTile = _gameArea
                .Tiles
                .Where(t => t.X == 0 && t.Y == 0)
                .Single();

            Assert.AreSame(EmptyTile.EmptyImage, newTile.Image, "New tile image is not the same as the current tile image");


        }

    }
}
